/*
****************************************************************************************
* @FilePath     : protocol_cmd.c
* @brief        : 
* @author       : L0131 - guomingpeng 952856693@qq.com
* @attention    : Copyright (c) 2024 awptech.co.ltd. All rights reserved.
****************************************************************************************
*/
#include "protocol_cmd.h"
#include "protocol_link.h"
#include "cmsis_os.h"
// #include "elog.h"
// #include "app_bsp.h"
// #include "app_nonlinear.h"
// #include "app_nonlinear_para.h"
// #include "app_sys.h"
// #include "non_comm.h"
// #include "app_at6xx.h"

#define LOG_TAG                             "protocol-cmd"
#define TX_HEADH        (0x55)
#define TX_HEADL        (0xAA)
#define RX_HEADH        (0xAA)
#define RX_HEADL        (0x55)
#define TX_TAILH        (0x5A)
#define TX_TAILL        (0x5A)
#define RX_TAILH        (0xA5)
#define RX_TAILL        (0xA5)


#define HOfWord(x)                          (*((uint8_t *)&(x) + 1))
#define LOfWord(x)                          (*((uint8_t *)&(x) + 0))

#define CMD_RX_BUFF_SIZE           (512)

typedef enum
{
    STEP_HEADER_H = 0,
    STEP_HEADER,
    STEP_LENGTH_H,
    STEP_LENGTH,
    STEP_DATA,
    STEP_TAIL_H,
    STEP_TAIL
}UnpackStep;

typedef struct {
    uint8_t id;
    uint8_t mode;
    uint8_t data[];
} protocol_link_received_packet_t;

/******************* 发送包定义 *********************/

typedef struct
{
	UnpackStep unpack_step;
	uint16_t max_len;
	uint16_t len;
	uint16_t index;
	uint8_t data_buf[512];
}RecvSocket;

static uint8_t cmd_rx_buff[CMD_RX_BUFF_SIZE] = {0};
static RecvSocket gRecvSocket;

osMessageQueueId_t protocol_cmd_send_queue_handler = NULL;
const osMessageQueueAttr_t protocol_cmd_send_queue_attributes = {
  .name = "protocol_cmd_send_queue"
};

static uint32_t protocol_cmd_pack(uint8_t *buf, uint32_t payload_len)
{
    uint32_t len = payload_len + 4;

    buf[0] = TX_HEADH;
    buf[1] = TX_HEADL;
    buf[2] = payload_len >> 8;
    buf[3] = payload_len;
    buf[len++] = TX_TAILH;
    buf[len++] = TX_TAILL;

    return len;
}

void _put_cmd_imdex(uint16_t cmd_index)
{
    if (protocol_cmd_send_queue_handler)
    {
        uint16_t comm_index = cmd_index;
        osMessageQueuePut(protocol_cmd_send_queue_handler, &comm_index, 0, 0);
    }
}

/* 获取通信链路状态 */
static void protocol_cmd_link_get_comm_handle(uint8_t *payload_buf)
{
    /* 通信链路状态 */
    // app_at6xx_info.connection_flag = 1;
    /* 回复ACK */
    _put_cmd_imdex(COM_LINK_ID);
}

/* 通信链路测试 */
static uint32_t protocol_cmd_link_comm_encode(uint8_t *buf)
{
    uint8_t *p;
    uint32_t payload_len = 0, len = 0;
    uint8_t ack = 1;

    p = &buf[4];
    p[payload_len++] = COM_LINK_ID;
    p[payload_len++] = ack;

    len = protocol_cmd_pack(buf, payload_len);
    return len;
}

static const protocol_cmd_handle_t protocol_cmd_handle_table[] = 
{
    {
        .cmd_index = COM_LINK_ID, 
        .set = NULL, 
        .get = protocol_cmd_link_get_comm_handle,
        .send_handle = protocol_cmd_link_comm_encode, 
    },

};

void protocol_cmd_send_data_encode(uint8_t *buf, uint32_t *len)
{
    osStatus_t ret;
    uint16_t comm_index = 0;

    *len = 0;
    if (!protocol_cmd_send_queue_handler)
    {
        return;
    }

    ret = osMessageQueueGet(protocol_cmd_send_queue_handler, &comm_index, 0, 0);
    if (ret != osOK)
    {
        return;
    }

    for (uint16_t i = 0; i < sizeof(protocol_cmd_handle_table) / sizeof(protocol_cmd_handle_t); i++)
    {
        if (protocol_cmd_handle_table[i].cmd_index == comm_index)
        {
            
            if (protocol_cmd_handle_table[i].send_handle)
            {
                *len = protocol_cmd_handle_table[i].send_handle(buf);
            }
            break;
        }
    }
}

static uint16_t Bytes_To_UINT16_LE(uint8_t* pData)
{
    return (pData[1] | (pData[0] << 8));
}

static int receive_comm_valid_check(uint8_t byte)
{
    int ret_int = -1;
    switch (gRecvSocket.unpack_step)
    {
        case STEP_HEADER_H:
        {
            if(RX_HEADH==byte)
            {
            	gRecvSocket.unpack_step = STEP_HEADER;
            }
        }break;
        case STEP_HEADER:
        {
            if(RX_HEADL==byte)
            {
            	gRecvSocket.unpack_step = STEP_LENGTH_H;
            }
            else
            {
            	gRecvSocket.unpack_step = STEP_HEADER_H;
            }
        }break;
        case STEP_LENGTH_H:
        {
        	gRecvSocket.data_buf[0] = byte;
        	gRecvSocket.unpack_step = STEP_LENGTH;
        }break;
        case STEP_LENGTH:
        {
        	gRecvSocket.data_buf[1] = byte;
        	gRecvSocket.len = Bytes_To_UINT16_LE(gRecvSocket.data_buf);
            if(gRecvSocket.max_len<gRecvSocket.len)
            {
            	gRecvSocket.unpack_step = STEP_HEADER_H;
            }
            else
            {
                gRecvSocket.index = 0;
                gRecvSocket.unpack_step = STEP_DATA;
            }
        }break;
        case STEP_DATA:
        {
        	gRecvSocket.data_buf[gRecvSocket.index++] = byte;
            if(gRecvSocket.len<=gRecvSocket.index)
            {
            	gRecvSocket.unpack_step = STEP_TAIL_H;
            }
        }break;
        case STEP_TAIL_H:
        {
            if(RX_TAILH==byte)
            {
            	gRecvSocket.unpack_step = STEP_TAIL;
            }
            else
            {
            	gRecvSocket.unpack_step = STEP_HEADER_H;
            }
        }break;
        case STEP_TAIL:
        {
            if(RX_TAILL==byte)
            {
            	ret_int = gRecvSocket.len;
            }
            gRecvSocket.unpack_step = STEP_HEADER_H;
        }break;
    }

    return ret_int;
}

static void receive_comm_decode(const uint8_t *buff, uint32_t len)
{
    uint8_t id;
    uint8_t mode = 0;
    uint8_t *data = NULL;
    protocol_link_received_packet_t *received_pack;

    /* 获取ID */
    received_pack = (protocol_link_received_packet_t *)buff;
    id = received_pack->id;
    if (len >= 2)
    {
        mode = received_pack->mode;
    }
    if (len >= 3)
    {
        data = received_pack->data;
    }

#if _PROTOCOL_LINK_DEBUG_EN
    log_d("id: %d, mode: %d", received_pack->id, received_pack->mode);
    log_d("receive: %d %d %d %d %d %d", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
#endif

    for (uint16_t i = 0; i < sizeof(protocol_cmd_handle_table) / sizeof(protocol_cmd_handle_t); i++)
    {
        if (protocol_cmd_handle_table[i].cmd_index == id)
        {
            if (mode)
            {
                if (protocol_cmd_handle_table[i].set)
                {
                    protocol_cmd_handle_table[i].set(data);
                }
            }
            else
            {
                if (protocol_cmd_handle_table[i].get)
                {
                    protocol_cmd_handle_table[i].get(data);
                }
            }
            break;
        }
    }
}

static void receive_data_handle(uint8_t *buff, uint32_t len)
{
    int comm_len;

    for(uint32_t i = 0; i < len; i++)
    {
        comm_len = receive_comm_valid_check(buff[i]);
        if (comm_len > 0)
        {
            printf("222 recv len: %d, ", comm_len);
            printf("data: ");
            for (uint32_t i = 0; i < comm_len; i++)
            {
            	printf("0x%02X ", gRecvSocket.data_buf[i]);
            }
            printf("\r\n\r\n");

            receive_comm_decode(gRecvSocket.data_buf, comm_len);
        }
    }
}

void protocol_cmd_handle(void)
{
    uint32_t len = 0;

    gRecvSocket.index = 0;
    gRecvSocket.max_len = 512;
    gRecvSocket.unpack_step = STEP_HEADER_H;

    protocol_cmd_send_queue_handler = osMessageQueueNew(10, sizeof(uint16_t), &protocol_cmd_send_queue_attributes);

    for (;;)
    {
        static uint32_t test_tick = 0;
        test_tick++;
        if (test_tick > 100)
        {
            test_tick = 0;
            // log_d("protocol_cmd loop \r\n");
        }

        PROTOCOL_LINK_RECV_DATA(cmd_rx_buff, &len, osWaitForever);
        if (len)
        {
            printf("111recv len: %ld, ", len);
            printf("data: ");
            for (uint32_t i = 0; i < len; i++)
            {
            	printf("0x%02X ", cmd_rx_buff[i]);
            }
            printf("\r\n\r\n");

            receive_data_handle(cmd_rx_buff, len);
        }
    }
}
